package work.smallRulesGui;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedList;

public class IOUtil {
	public static StringBuffer beforeAppsBuff = new StringBuffer();
	public static StringBuffer afterAppsBuff = new StringBuffer();
	public static String quote = "";
	public static String appName = "";
	public static LinkedList<String> flowsOrder = new LinkedList<String>();
	public static LinkedList<String> handlersOrder = new LinkedList<String>();
	
	private static final String appStr = "Applications {";
	private static boolean passedBeforeApps = false;
	private static HashMap<String, String> handlerDescs = new HashMap<String, String>();
	private static HashMap<String, String> handlerTcs = new HashMap<String, String>();

	static final void loadFile(File fl) {
		SmallRuleGui.frame.setTitle("Small rulegui - " + fl.getName());
		SmallRuleGui.statusLabel.setText("Loading...");
		SmallRuleGui.actionsMap.clear();
		SmallRuleGui.actionIndexes.clear();
		SmallRuleGui.pathStack.clear();
		SmallRuleGui.pathIndex = 0;
		
		beforeAppsBuff.setLength(0);
		afterAppsBuff.setLength(0);
		handlerDescs.clear();
		handlerTcs.clear();
		flowsOrder.clear();
		handlersOrder.clear();
		quote = "";
		passedBeforeApps = false;
		try {
			BufferedReader br = new BufferedReader(new FileReader(fl));
			boolean appSection = false, flowsSection = false, handlerSection = false, handlerCode = false, flowCode = false, handlerTestCode = false;
			String str = null, cHandler = "", cHandlerName = null, cHandlerTests = "", cFlow = "", cFlowName = null;
			while((str = br.readLine()) != null) {
				if(str.equals(appStr)) {
					appSection = true;
					beforeAppsBuff.append(str).append("\n");
					str = br.readLine();
					beforeAppsBuff.append(str).append("\n");
					str = str.trim();
					str = str.substring(0, str.length() - 2);
					appName = str.replaceAll("'", "");
					continue;
				}
				if(str.startsWith("        'Rules' {") || str.startsWith("        Rules {")) {
					if(str.indexOf("'") != -1) {
						quote = "'";
					}
					flowsSection = true;
					handlerSection = false;
					continue;
				}
				if(str.equals("        'Handler' {") || str.equals("        Handler {")) {
					flowsSection = false;
					handlerSection = true;
					continue;
				}
				if(!flowsSection && !handlerSection) {
					if(!passedBeforeApps) {
						beforeAppsBuff.append(str).append("\n");
					} else {
						afterAppsBuff.append(str).append("\n");
					}
					continue;
				}
				if(str.equals("        'Tests' {") || str.equals("        Tests {")) {
					passedBeforeApps = true;
					afterAppsBuff.append(str).append("\n");
					flowsSection = false;
					handlerSection = false;
					continue;
				}
				if(handlerSection) {
					if(str.equals("                }.")) {
						SmallRuleGui.handlersMap.put(cHandlerName, cHandler);
						ArrayList<String> list = new ArrayList<String>();
						list.add(cHandler.length() + "|" + cHandler);
						SmallRuleGui.actionsMap.put("h" + cHandlerName, list);
						handlersOrder.add(cHandlerName);
						cHandler = "";
						handlerCode = false;
						continue;
					}
					if(str.startsWith("            ") && str.endsWith(" {") && !str.startsWith("             ")) {
						cHandlerName = str.trim().replaceAll("'", "");
						cHandlerName = cHandlerName.substring(0, cHandlerName.length() - 2);
						continue;
					}
					if(str.equals("                'JCode' = {") || str.equals("                JCode = {")) {
						handlerCode = true;
						continue;
					}
					if(handlerCode) {
						cHandler += str.substring(20) + "\n";
						continue;
					}
					if(str.equals("                'Tests' {") || str.equals("                Tests {")) {
						handlerTestCode = true;
						cHandlerTests += str + "\n";
						continue;
					}
					if(handlerTestCode) {
						cHandlerTests += str + "\n";
						if(str.equals("                }")) {
							handlerTestCode = false;
							handlerTcs.put(cHandlerName, cHandlerTests);
							cHandlerTests = "";
						}
						continue;
					}
					if(str.startsWith("                'Description' = ") || str.startsWith("                Description = ")) {
						if(!str.endsWith(" = {")) {
							handlerDescs.put(cHandlerName, str);
						} else {
							StringBuffer buff = new StringBuffer();
							buff.append("\n" + str);
							while(!str.equals("                }.")) {
								str = br.readLine();
								buff.append("\n" + str);
							}
							handlerDescs.put(cHandlerName, buff.toString().substring(1));
						}
						continue;
					}
				}
				if(flowsSection) {
					if(str.equals("            }.")) {
						SmallRuleGui.flowsMap.put(cFlowName, cFlow);
						ArrayList<String> list = new ArrayList<String>();
						list.add(cFlow.length() + "|" + cFlow);
						SmallRuleGui.actionsMap.put("f" + cFlowName, list);
						flowsOrder.add(cFlowName);
						cFlow = "";
						flowCode = false;
						continue;
					}
					if(!flowCode && str.startsWith("            '") && str.endsWith("'")) {
						String s = str.trim().substring(1);
						cFlowName = s.substring(0, s.indexOf("'"));
						s = s.substring(s.indexOf("'") + 1);
						s = s.substring(s.indexOf("'") + 1);
						cFlow = s.substring(0, s.indexOf("'"));
						SmallRuleGui.flowsMap.put(cFlowName, cFlow);
						ArrayList<String> list = new ArrayList<String>();
						list.add(cFlow.length() + "|" + cFlow);
						SmallRuleGui.actionsMap.put("f" + cFlowName, list);
						flowsOrder.add(cFlowName);
						cFlow = "";
						flowCode = false;
						continue;
					}
					if(str.startsWith("            ") && str.endsWith(" = {") && !str.startsWith("             ")) {
						cFlowName = str.trim().replaceAll("'", "");
						cFlowName = cFlowName.substring(0, cFlowName.length() - 4);
						flowCode = true;
						continue;
					}
					if(flowCode) {
						cFlow += str.substring(16) + "\n";
					}
				}
			}
			br.close();
			
			SmallRuleGui.handlersModel.removeAllElements();
			for(String handlerName : SmallRuleGui.handlersMap.keySet()) {
				SmallRuleGui.handlersModel.addElement(handlerName);
			}
			SmallRuleGui.flowsModel.removeAllElements();
			for(String flowName : SmallRuleGui.flowsMap.keySet()) {
				SmallRuleGui.flowsModel.addElement(flowName);
			}
			SmallRuleGui.statusLabel.setText("File openened!");
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	static final void saveFile(File fl) {
		SmallRuleGui.statusLabel.setText("Saving...");
		try {
			PrintWriter pw = new PrintWriter(new FileWriter(fl));
			pw.print(beforeAppsBuff.toString());
			pw.println("        " + quote + "Rules" + quote + " {");
			for(String flowName : flowsOrder) {
				pw.println("            " + quote + flowName + quote + " = {");
				String[] lines = SmallRuleGui.flowsMap.get(flowName).split("\n");
				for(String s : lines) {
					pw.println("                " + s);
				}
				pw.println("            }.");
			}
			pw.println("        }");
			pw.println("        " + quote + "Handler" + quote + " {");
			//for(Entry<String, String> en : SmallRuleGui.handlersMap.entrySet()) {
			for(String handlerName : handlersOrder) {
				pw.println("            " + quote + handlerName + quote + " {");
				if(handlerDescs.containsKey(handlerName)) {
					pw.println(handlerDescs.get(handlerName));
				}
				pw.println("                " + quote + "JCode" + quote + " = {");
				String[] lines = SmallRuleGui.handlersMap.get(handlerName).split("\n");
				for(String s : lines) {
					pw.println("                    " + s);
				}
				pw.println("                }."); 
				if(handlerTcs.containsKey(handlerName)) {
					pw.println(handlerTcs.get(handlerName));
				}
				pw.println("            }");
			}
			pw.println("        }");
			pw.print(afterAppsBuff);
			pw.close();
			SmallRuleGui.statusLabel.setText(fl.getName() + " saved");
		} catch(Exception ex) {
			ex.printStackTrace();
		}
	}
}
